<template>
  <Dialog v-model:visible="visible.runModal" header="运行工具" :style="{ maxWidth: '70rem', minWidth:'10rem' }">
    <form @submit.prevent='onSubmit'>
      <div class="formgroup-inline align-items-center grid grid-cols-4 gap-4">
        <div v-for="(item, index) in formState.args" class="mt-5 mb-5">
          <label :for="item.id" class="text-sm font-semibold leading-6 text-gray-900">{{ item.name }}</label>
          <div class="flex flex-column mt-2">
            <InputText v-if="item.type === 'one_str'" :id="item.id" v-model="item.value" class="w-full"
                       autocomplete="off"/>

            <Textarea v-else-if="item.type === 'multi_str'" :id="item.id" v-model="item.value" rows="5"
                      cols="50"
                      autocomplete="off"/>

            <div v-else-if="item.type === 'bool'" class="flex flex-wrap gap-3">
              <div class="flex align-items-center">
                <RadioButton v-model="item.value" inputId="ingredient1" name="pizza"
                             :value="true" :id="item.id"/>
                <label for="ingredient1" class="ml-2">是</label>
              </div>
              <div class="flex align-items-center">
                <RadioButton v-model="item.value" inputId="ingredient2" name="pizza" :value="false"
                             :id="item.id"/>
                <label for="ingredient1" class="ml-2">否</label>
              </div>
            </div>

            <div v-else-if="item.type === 'enums'" class="flex flex-wrap gap-3">
              <Select class='w-8rem' v-model="item.value" :options="item.enums"
                      aria-labelledby="basic"/>
            </div>
            <div v-else-if="item.type === 'password'" class="flex flex-wrap gap-3">
              <Password v-model="item.value" :feedback="false"/>
            </div>
            <div v-else-if="item.type === 'number'" class="flex flex-wrap gap-3">
              <InputNumber v-model="item.value"/>
            </div>
            <div v-else-if="item.type === 'image'" class="flex flex-wrap gap-3">

              <FileUpload v-if="!src" @select="onFileSelect" accept="image/*" customUpload
                          :pt="{content:{style: {'display': 'none'}}, header:{style: {'padding': '0', 'border': '0'}}}">
                <template #header="{ chooseCallback, uploadCallback, clearCallback, files }">
                  <Button @click="chooseCallback()" icon="pi pi-image" text
                          severity="secondary"></Button>
                </template>
              </FileUpload>
              <img v-if="src" :src="src" alt="Image" class="shadow-md rounded-xl w-24"
                   style="filter: grayscale(100%)"/>
            </div>
            <small class="p-error">
              {{ errors[item.id] }}
            </small>
          </div>
        </div>
      </div>

      <div style="width:100%;display: flex; justify-content: space-between;" class='mb-3'>
        <Button @click="copyContent" severity="secondary">复制</Button>
        <div>
          <Button type="submit" label="执行" :loading="debugLoading"/>
          <Button class="mb-3 ml-2" severity="success" @click="eventShare($event)">分享</Button>
          <ConfirmPopup group="headless">
            <template #container="{ message, acceptCallback, rejectCallback }">
              <div class="rounded p-4">
                <span>{{ shareContent }}</span>
                <div class="flex items-center gap-2 mt-4">
                  <Button label="复制" @click="acceptCallback" size="small"></Button>
                  <!--                  <Button label="Cancel" outlined @click="rejectCallback" severity="secondary" size="small"-->
                  <!--                          text></Button>-->
                </div>
              </div>
            </template>
          </ConfirmPopup>

          <Button key="back" danger @click="() => discontinue()" severity="secondary" class='ml-2'>终止
          </Button>
        </div>
      </div>
    </form>
    <!--      <div class="p-3" style="background-color: red">-->
    <div ref="xtermContainer"/>
    <!--      </div>-->
  </Dialog>
  <!--  <a-modal-->
  <!--      title='工具执行'-->
  <!--      width='60%'-->
  <!--      v-model:open="visible.runModal"-->
  <!--      @ok="() => toolDebug(data?.data.detail._id)"-->
  <!--      :mask="false"-->
  <!--      :footer="false"-->
  <!--  >-->
  <!--    <div style="cursor: default">-->
  <!--      <template v-dialog-drag></template>-->
  <!--      <a-spin :spinning="loading">-->
  <!--        <a-form-->
  <!--            ref="refForm"-->
  <!--            layout="inline"-->
  <!--            :model="formState"-->
  <!--        >-->
  <!--          <a-form-item-->
  <!--              v-for="(item, index) in formState.args"-->
  <!--              :key="item.id"-->
  <!--              :label="item.name"-->
  <!--              style="height: 50px"-->
  <!--              :name="['args', index, 'default_value']"-->
  <!--              :rules="{required: item.require, message: item.name + '不能为空',trigger: 'change'}"-->
  <!--          >-->
  <!--            <a-input v-if="item.type === 'one_str'" v-model:value="item.default_value"/>-->
  <!--            <a-textarea style="width: 87%" v-else-if="item.type === 'multi_str'" :autosize="{maxRows: 1 }"-->
  <!--                        v-model:value="item.default_value"/>-->
  <!--            <a-input-number style="width: 80%" v-else-if="item.type === 'number'"-->
  <!--                            v-model:value="item.default_value"></a-input-number>-->
  <!--            <a-input-password v-else-if="item.type === 'password'" v-model:value="item.default_value"/>-->
  <!--            <a-radio-group style="width: 120px" v-else-if="item.type === 'bool'"-->
  <!--                           v-model:value="item.default_value">-->
  <!--              <a-radio :value="true">是</a-radio>-->
  <!--              <a-radio :value="false">否</a-radio>-->
  <!--            </a-radio-group>-->
  <!--            <a-select-->
  <!--                v-else-if="item.type === 'enums'"-->
  <!--                style="width: 150px"-->
  <!--                v-model:value="item.default_value"-->
  <!--                :options="item.enumsDefault"-->
  <!--            >-->
  <!--            </a-select>-->
  <!--            <a-tag v-else-if="item.type === 'file'" color="blue">-->
  <!--              {{ item.default_value }}-->
  <!--            </a-tag>-->
  <!--            <a-button v-if="item.type === 'file'"-->
  <!--                      style="width: 50px;margin-left: 10px"-->
  <!--                      size="small"-->
  <!--                      @click="() => {visible.setArgsFile = true;argsSelectIndex = index}"-->
  <!--            >设置-->
  <!--            </a-button>-->
  <!--            <FullscreenOutlined v-if="item.type === 'multi_str'" style="line-height: 30px;margin-left: 10px"-->
  <!--                                @click="() => inputFull(index)"></FullscreenOutlined>-->
  <!--          </a-form-item>-->
  <!--        </a-form>-->
  <!--        <div style="width:100%;height: 60px; display: flex; justify-content: space-between">-->
  <!--          <a-space>-->
  <!--            <a-button @click="copyContent">复制</a-button>-->
  <!--&lt;!&ndash;            <a-button>sdf</a-button>&ndash;&gt;-->
  <!--          </a-space>-->
  <!--          <a-space>-->
  <!--            <a-button key="submit" type="primary" :loading="debugLoading" @click="() => toolDebug(data?.data.detail._id)">-->
  <!--              执行-->
  <!--            </a-button>-->
  <!--            <a-button key="back" danger @click="() => discontinue()">终止</a-button>-->
  <!--          </a-space>-->
  <!--        </div>-->

  <!--        <div ref="xtermContainer" id='terminalContainer'/>-->
  <!--      </a-spin>-->
  <!--    </div>-->
  <!--  </a-modal>-->

  <!--<a-modal title="设置参数值" v-model:open="visible.valueModal" @ok="setInputValueFunc">-->
  <!--  <a-textarea v-model:value="showValue.value" autoSize></a-textarea>-->
  <!--</a-modal>-->
  <!--<a-modal style="width: 80%" v-model:open="visible.setArgsFile" title="设置文件">-->
  <!--  <FileView :select-file="setSelectFile"></FileView>-->
  <!--</a-modal>-->
</template>
<script setup>
import {ref, defineExpose, reactive, watch, onMounted} from "vue";
import {useRequest} from 'ahooks-vue';
import {ApiDetail, ApiDiscontinue, ApiShare} from "@/api/toolkit.js";
import 'xterm/css/xterm.css'
import Select from 'primevue/select';
import {Terminal} from 'xterm';
import {FitAddon} from 'xterm-addon-fit'
import storage from "store";
import {ACCESS_TOKEN} from "@/store/mutation-types.js";
import useClipboard from 'vue-clipboard3'
import {useForm} from 'vee-validate';
import * as yup from 'yup';
import {useConfirm} from "primevue/useconfirm";
import {cloneDeep} from "lodash-es";
import imageCompression from 'browser-image-compression';

const isMobile = ref(window.innerWidth < 768);
const {toClipboard} = useClipboard()

defineExpose({
  show: (index) => {
    visible.runModal = true;
    run({id: index})
  },
  setContent: (content) => {
    newContent.value = content
  }
})
const confirm = useConfirm();

const xtermContainer = ref()

const term = ref()
const refForm = ref()
const argsSelectIndex = ref(-1);
const visible = reactive({
  runModal: false,
  valueModal: false,
  setArgsFile: false
})
const newContent = ref()
const formState = ref({})
const debugLoading = ref(false)
const showValue = ref({
  index: 0,
  value: ''
})

const shareContent = ref()


watch(xtermContainer, (newValue) => {
  if (newValue !== undefined && newValue !== null) {
    term.value = new Terminal({
      fontSize: 14,
      convertEol: false, // 启用时，光标将设置为下一行的开头
      rendererType: 'canvas', // 渲染类型
      cursorBlink: false, // 光标闪烁
      theme: {
        background: '#060101', // 背景色
        cursor: 'help' // 设置光标
      },
      scrollback: 10000,
    })
    const fitAddon = new FitAddon();
    term.value.loadAddon(fitAddon);
    term.value.open(xtermContainer.value)
    fitAddon.fit();

  }
})

// API
const {data, loading, run} = useRequest(ApiDetail, {
  manual: true,
  onSuccess: e => {
    formState.value = e.data.detail
  },
})

const errors = ref({});
let pid = ''

function verifyForm() {
  const values = {}
  let is_exit = false
  console.log(formState.value.args)
  formState.value.args.forEach(item => {
    console.log(item.value)
    if (item.require && (item.value === '' || item.value === undefined || item.value === null)) {
      errors.value[item.id] = '该参数必填'
      is_exit = true
    } else {
      errors.value[item.id] = ''
      values[item.id] = item.value
    }
  })
  if (is_exit) {
    return
  }
  return values
}

const onSubmit = async () => {
  const values = verifyForm()
  if (values) {
    debugLoading.value = true
    const token = storage.get(ACCESS_TOKEN)
    initSocket({id: formState.value.id, content: newContent.value, args: values, token: token})
  }
}

function inputFull(index) {
  showValue.value.index = index
  showValue.value.value = formState.value.args[index]['default_value']
  visible.valueModal = true
}

function setInputValueFunc() {
  formState.value.args[showValue.value.index]['default_value'] = showValue.value.value
  visible.valueModal = false
}

function setSelectFile(path) {
  formState.value.args[argsSelectIndex.value]['default_value'] = path.join('/')
  visible.setArgsFile = false
}

const discontinue = async () => {
  const result = await ApiDiscontinue(pid)
  if (result.code === 0) {
    message.success(result.msg)
  } else {
    message.error(result.msg)
  }
}
const initSocket = (params) => {
  const protocol = document.location.protocol;
  let websocket_protocol = 'ws://'
  if (protocol === "https:") {
    websocket_protocol = 'wss://'

  }

  let isOk = false
  const socket = new WebSocket(websocket_protocol + window.location.host + '/ws/v1/toolkit/start')
  term.value.clear()
  // term.value.
  socket.onmessage = async e => {
    if (e.data instanceof Blob) {
      const text = await e.data.text();
      term.value.write(text);
    } else {
      try {
        const data = JSON.parse(e.data);
        if (data.end === true) {
          isOk = data.status
        } else if (data.end === false) {
          pid = data.pid
        }
      } catch (error) {
        // 如果不是 JSON 类型，则将其写入终端
        term.value.write(e.data);
      }
    }
  }


  socket.onopen = () => {
    socket.send(JSON.stringify(params))
    term.value.focus()
  }

  socket.onclose = e => {
    debugLoading.value = false
  }
  term.value.onKey(async data => {
    if (data.key === '\x03') {
      // 复制
      await toClipboard(term.value.getSelection())
    }
  })
}

const copyContent = async () => {
  term.value.selectAll()
  await toClipboard(term.value.getSelection())
}

const eventShare = async (event) => {
  const keepEvent = cloneDeep(event)
  const values = verifyForm()
  if (values) {
    confirm.require({
      target: keepEvent.currentTarget,
      group: 'headless',
      message: 'Are you sure you want to proceed?',
      icon: 'pi pi-exclamation-triangle',
      rejectProps: {
        label: 'Cancel',
        severity: 'secondary',
        outlined: true
      },
      acceptProps: {
        label: '复制'
      },
      accept: async () => {
        await toClipboard(shareContent.value)
        // toast.add({severity: 'info', summary: 'Confirmed', detail: 'You have accepted', life: 3000});
      },
      // reject: () => {
      //   toast.add({severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000});
      // }
    });

    const result = await ApiShare({id: formState.value.id, content: newContent.value, args: values})
    shareContent.value = document.location.protocol + '//' + document.location.host + "/#/share?share_id=" + result.data.share_id

  }
}
const src = ref(null);

function onFileSelect(event) {
  const file = event.files[0];
  const reader = new FileReader();

  reader.onload = async (e) => {
    src.value = e.target.result;
  };

  reader.readAsDataURL(file);
}

</script>

<style>
.xterm-cursor {
  visibility: hidden;
}
</style>